﻿using Gameplay.RTS.ScriptConfig;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Mars.Got;
using Random = UnityEngine.Random;
using EffectElement = com.youzu.warh.protocol.EffectElement;
namespace Yoozoo.Gameplay.RTS
{
    public class SkillHit
    {
        private ERtsSkillState _status;
//        private EffectElement damage;
        private int skillId;
        private float damageDelayTime;
        private float effectDelayTime;
        float skillStartTime;
        float skillAutoDestroyTime;
        MarchEntity march;
        MarchEntity target;
        int textType;
        int authorType;
        bool isRelatedToSelf;
        float hitStartTime;
        int effectId;
        int flyType;
        int flyTextNum;
        List<Vector2Int> flyTextNumInterval;
        int skill_effect_type;
        List<int> shake_cd;
        int shake_cdTimes;
        int c_effectId;
        int c_buffId;
        private int elementId;
        private int skillLv;
        private int damageAmount;
        private long sourceId;
        private com.youzu.warh.protocol.TargetCoordinateType sourceType;
        private float scale = 1;

        private bool m_isCarSkill = false;

        private long targetTid;
        private long marchTid;
        
        internal void Initialize(EffectElement element, MarchEntity march, float startTime, MarchEntity marchEntity, int textType,bool isCarSkill = false)
        {
            _status = ERtsSkillState.NotPlay;
            skillId = element.skillId;
            skillLv = element.skillLv;
            elementId = element.elementId;
            sourceId = element.source.uid;
            sourceType = element.source.type;
            damageAmount = GetAmountSum(element);
            damageDelayTime = -1;
            effectDelayTime = -1;
            skillStartTime = startTime;
            skillAutoDestroyTime = 8;
            this.march = march;
            target = march.GetBattleTarget();
            targetTid = target?.Tid ?? 0;
            marchTid = march?.Tid ?? 0;
            this.textType = textType;

            isRelatedToSelf = target != null && target.Team == MarchHelper.TeamSelf || march != null && march.Team == MarchHelper.TeamSelf;

            m_isCarSkill = isCarSkill;
            
            var sourceMarch = ArmyManager.Instance.MarchManager.GetMarchEntityByIdAndType(sourceId,sourceType);
            scale = 1;
            if (sourceMarch != null)
            {
                if (sourceMarch.Team != (int) MarchTeam.Self )
                {
                    scale = 0.8f;
                }
            }
        }
 
        private void Play(float curTime)
        {
            hitStartTime = curTime;
            _status = ERtsSkillState.Playing;
            damageDelayTime = 0;
            GetDamageDelayTime();
            var elementConfig = ArmyManager.Instance.ResourceManager.GetSkillElementRtsConfig(elementId);
            if (elementConfig != null)
            {
                effectId = (int)elementConfig.skill_effect_id.x;
                effectDelayTime = elementConfig.skill_effect_id.y / 1000f;
                flyType = elementConfig.float_text_type;
                flyTextNum = elementConfig.float_hp_num_cd.Count;
                flyTextNumInterval = elementConfig.float_hp_num_cd;
                skill_effect_type = elementConfig.skill_effect_type;
                shake_cd = elementConfig.shake_cd;
                if (shake_cd!= null)
                {
                    shake_cdTimes = shake_cd.Count;
                }
                else
                {
                    shake_cdTimes = 0;
                }
            }
        }

        private void GetDamageDelayTime()
        {
            var config = ArmyManager.Instance.ResourceManager.GetHeroSkillConfig(skillId,skillLv);
            if (config != null)
            {
                for (int i = 0; i < config.child1_element.Count; i++)
                {
                    var elementId = config.child1_element[i];
                    if (elementId == this.elementId && i < config.child1_element_delay.Count)
                    {
                        if (config.child1_element_delay[i] > 0)
                        {
                            damageDelayTime = config.child1_element_delay[i] / 1000f;
                        }
                        break;
                    }
                }

                for (int i = 0; i < config.child2_element.Count; i++)
                {
                    var elementId = config.child2_element[i];
                    if (elementId == this.elementId && i < config.child2_element_delay.Count)
                    {
                        if (config.child2_element_delay[i] > 0)
                        {
                            damageDelayTime = config.child2_element_delay[i] / 1000f;
                        }
                        break;
                    }
                }

                for (int i = 0; i < config.child3_element.Count; i++)
                {
                    var elementId = config.child3_element[i];
                    if (elementId == this.elementId && i < config.child3_element_delay.Count)
                    {
                        if (config.child3_element_delay[i] > 0)
                        {
                            damageDelayTime = config.child3_element_delay[i] / 1000f;
                        }
                        break;
                    }
                }
            }
            else
            {
                damageDelayTime = 0;
            }
        }

        internal void Update(float curTime)
        {
            if (_status == ERtsSkillState.NotPlay)
            {
                if (curTime >= skillStartTime)
                {
                    Play(curTime);
                }
                else
                {
                    return;
                }
            }
            if (curTime > skillAutoDestroyTime + skillStartTime)
            {
                Dispose();
            }
            if (_status == ERtsSkillState.Playing)
            {
                CheckFlyText(curTime);
                CheckEffect(curTime);
            }
        }
        
        private void CheckFlyText(float curTime)
        {
            if (march == null || march.Tid != marchTid)
            {
                return;
            }

            if (damageDelayTime >= 0 && curTime - hitStartTime > damageDelayTime)
            {
                
                damageDelayTime = -1;
                var times = flyTextNum;
                if (times > 0)
                {
                    var damageAmount = this.damageAmount;
                    if (times == 1)
                    {
                        FlyText(damageAmount);
                        if (MarchHelper.ShowRtsSkillEffect())
                        {
                            if (damageAmount > 0)
                            {
                                ShowFakeKnockBack();
                            }
                        }
                    }
                    else
                    {
                        FlyRepeatText(damageAmount, flyTextNumInterval);
                        if (MarchHelper.ShowRtsSkillEffect())
                        {
                            if (damageAmount > 0)
                            {
                                for (int i = 0; i < flyTextNumInterval.Count; i++)
                                {
                                    var interval = flyTextNumInterval[i][0];
                                    var temp = i;
                                    Timers.inst.Add(interval / 1000f, 1, (obj) => {
                                        ShowFakeKnockBack(temp);
                                    });
                                }
                            }
                        }
                    }

                    if (target!= null && target.Team == MarchHelper.TeamSelf && target.MarchInfo.IsInBattleState && !target.IsWaitDelete && target.MarchInfo.MarchType != MarchType.DIE_5 && target.Tid == targetTid)
                    {
                        if (march!=null && march.MarchInfo.IsInBattleState && !march.IsWaitDelete && march.MarchInfo.MarchType != MarchType.DIE_5 && marchTid == march.Tid)
                        {
                            if (ArmyManager.Instance.ElementManager.CanShake(march.Position))
                            {
                                if (shake_cdTimes >= 1 && shake_cd[0] != 0)
                                {
                                    for (int i = 0; i < shake_cdTimes; i++)
                                    {
                                        var temp = i;
                                        Timers.inst.Add(shake_cd[i] / 1000f, 1, (obj) => {
                                            temp = i;
                                            ArmyManager.Instance.ElementManager.ShakeScreen();
                                        });
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void FlyRepeatText(int allDamage, List<Vector2Int> flyTextNumInterval)
        {
            var charStr = GetTxtChar();
            var myPosition = march.Position;
            Vector3 targetPosition = default;
            var AnimName = "sfx_ui_flytext_lj1"; //右边
            if (target != null)
            {
                targetPosition = target.Position;
                var targetScreenPos = WorldCameraManager.mainCamera.WorldToScreenPoint(targetPosition);
                var myScreenPos = WorldCameraManager.mainCamera.WorldToScreenPoint(myPosition);
                if (targetScreenPos.x > myScreenPos.x)
                    AnimName = "sfx_ui_flytext_lj2";
                
            }
            var priority = isRelatedToSelf ? 1 : 0;
            if (march.MarchInfo.IsInBattleState && march.MarchInfo.BuildingUid == 0 && !march.IsWaitDelete && march.MarchInfo.MarchType != MarchType.DIE_5 && march.Tid == marchTid)
            {
                RTSLuaCallCSharpManager.PlayRepeatText2(textType, charStr.ToString(), allDamage, scale, AnimName, flyTextNumInterval, myPosition, targetPosition, priority);
            }
        }

        private char GetTxtChar()
        {
            char text;
            if (flyType == 3 || flyType == 5)
            {
                text = '+';
            }
            else
            {
                text = '-';
            }
            return text;
        }
        private void ShowFakeKnockBack(int temp = 0)
        {
            if (target == null || march == null || targetTid != target.Tid || marchTid != march.Tid)
            {
                return;
            }

            if (flyType == 3 || flyType == 5)
            {
                return;
            }
            var tid = march.Tid;
            
            var selfPosition = march.Position;
            var targetPosition = target.Position;
            var times = flyTextNum;
            var knockSoldierCount = (int)(Random.Range(3, 6f) / times);
           
            march.FakeKnockBack(selfPosition - targetPosition, knockSoldierCount);
        }

        private void FlyText(int damageAmount)
        {
            if ((march != null && (march.IsReadyToRemove() || marchTid != march.Tid)) || (target != null && (target.IsReadyToRemove() || targetTid != target.Tid)))
            {
                return;
            }
            if (flyType < 100 && flyType != 0 && damageAmount != 0)
            {
                FlyTextAudio audioType = FlyTextAudio.NONE;
                var text = getTxt(damageAmount);
                int priority = isRelatedToSelf ? 1 : 0;

                //是自己的部队需要播放飘字音效
                if (march != null && march.RtsServerInfo != null && march.RtsServerInfo.team == (int)MarchTeam.Self)
                {
                    audioType = FlyTextManager.Instance.GetFlyTextAudioBySoldierType(march.RtsServerInfo.SoldierType);
                }
                if (march.MarchInfo.IsInBattleState)
                {
                    
                    if (target != null)
                    {
                        RTSLuaCallCSharpManager.FlyText(textType, march.Position, text, scale, target.Position, null, priority, audioType);
                    }
                    else 
                    {
                        RTSLuaCallCSharpManager.FlyText(textType, march.Position, text, scale, default, null, priority, audioType);
                    }
                }
            }
        }
        
        private string getTxt(int damageAmount)
        {
            string text;
            if (flyType == 3 || flyType == 5)
            {
                text = $"+{damageAmount}";
            }
            else
            {
                text = $"-{damageAmount}";
            }
            return text;
        }

        private int GetAmountSum(EffectElement element)
        {
            var sum = element.amount;
            return sum;
        }

        private void CheckEffect(float curTime)
        {
            if (effectDelayTime >= 0 && curTime - hitStartTime > effectDelayTime)
            {
                effectDelayTime = -1;
                Vector3 effectTargetPosition = default;
                
                var sourceMarch = ArmyManager.Instance.MarchManager.GetMarchEntityByIdAndType(sourceId,sourceType);
                if (sourceMarch != null)
                {
                    effectTargetPosition = sourceMarch.Position;
                }
                Vector3 sourcePosition;
                if (effectTargetPosition!=default)
                {
                    sourcePosition = effectTargetPosition;
                }
                else
                {
                    sourcePosition = march.Position;
                }

                Vector3 targetPosition;
                if (skill_effect_type == 1)
                {
                    targetPosition = march.Position;
                }
                else
                {
                    targetPosition = march.GetRandomSoldierPosition();
                }
                if (march.MarchInfo.IsInBattleState && !march.IsWaitDelete && march.MarchInfo.MarchType != MarchType.DIE_5 && march.Tid == marchTid)
                {
                    var isRelatedToSelf = march.Team == 0 || (target != null && target.Team == 0);
					if(effectId > 0){
	                    if (!m_isCarSkill)
	                    {
	                        c_effectId = RTSLuaCallCSharpManager.PlayEffect(effectId, sourcePosition, targetPosition, march.Team, isRelatedToSelf);
	                    }
	                    else
	                    {
	                        if (c_effectId == -1 || c_effectId == 0)
	                        {
	                            if (isRelatedToSelf)
	                            {
	                                c_effectId = RTSLuaCallCSharpManager.PlayBuffEffect(effectId, march, true);
	                            }
	                        }
	                    }
                    }
                }
            }
        }
        
        internal bool IsEnd()
        {
            return _status == ERtsSkillState.End;
        }

        internal void Dispose()
        {
            _status = ERtsSkillState.End;
            if (c_effectId >= 0)
            {
                RTSLuaCallCSharpManager.RemoveEffect(c_effectId, isRelatedToSelf);
            }
            c_effectId = 0;
            if (m_isCarSkill)
            {
                march?.DisposeSkillOutSide();
            }
            march = null;
            target = null;
            targetTid = 0;
            marchTid = 0;
            flyTextNumInterval = null;
            shake_cd = null;
        }

        internal void OnReset()
        {

        }

        /// <summary>
        /// 重置技能的时间(Buff用)
        /// </summary>
        public void ResetSkillTimer()
        {
            skillStartTime = TimeUtils.GetClientTickTime();
        }
    }
}
